﻿using System;
using System.Collections;
using System.Collections.Specialized;
using System.Security;
using System.Diagnostics;
using System.Data;
using System.Data.SqlClient;
using System.Threading;
using System.Configuration;

namespace Clueso
{   

    class Task
    {
        public string TaskId;
        public string FileName;
        public string Arguments;
        public string UserName="";
        public string Password="";
        public string Status;
        public string Response;
        public int LogDb;
    }

    class ScriptLauncher
    {
        public static ArrayList AllTasks = new ArrayList();
        static string ConnectionString;
        static string sqlGetTask;
        private delegate void LaunchTaskDelegate(Task T);

        static void Main(string[] args)
        {
            try
            {
                GetAppConfig();
                GetTasks();
                DoTasks();
            }
            catch (Exception e)
            {
                Console.WriteLine("{0} {1} {2}", e.Source, e.Message, e.StackTrace);
            }
        }

        static void GetAppConfig()
        {
            try
            {
                AppSettingsReader R = new AppSettingsReader();
                ConnectionString = (string)R.GetValue("connectionString", String.Empty.GetType());
                sqlGetTask = (string)R.GetValue("sqlGetTask", String.Empty.GetType());
            }
            catch (Exception e)
            {
                Console.WriteLine("{0} {1} {2}", e.Source, e.Message, e.StackTrace);
            }
        }

        static void GetTasks()
        {
            Task T;
            SqlConnection conn = null;

            try
            {
                conn = new SqlConnection(ConnectionString);
                conn.Open();

                SqlCommand cmd = new SqlCommand(sqlGetTask, conn);
                SqlDataReader rdr = null;

                rdr = cmd.ExecuteReader();

                string server_name;
                while (rdr.Read())
                {
                    T = new Task();
                    T.FileName = rdr.GetString(rdr.GetOrdinal("fullname"));

                    T.TaskId = rdr.GetInt32(rdr.GetOrdinal("task_id")).ToString();
                    T.LogDb = rdr.GetInt32(rdr.GetOrdinal("logdb"));
                    server_name = rdr.GetString(rdr.GetOrdinal("server_name"));

                    T.Arguments = rdr.GetString(rdr.GetOrdinal("arguments"));
                    T.Arguments = T.Arguments.Replace("$server_name$", server_name);


                    server_name = "";

                    AllTasks.Add(T);

                }

            }

            catch (Exception e)
            {
                Console.WriteLine("{0} {1} {2}", e.Source, e.Message, e.StackTrace);
            }
            finally
            {
                conn.Close();
            }


        }

        static void LaunchTask(Object stateInfo)
        {
            try
            {
                // Initalize Process 
                ProcessStartInfo Cmd = new ProcessStartInfo();

                Task T = (Task)stateInfo;
                Cmd.FileName = T.FileName;
                Cmd.Arguments = T.Arguments;
                Cmd.RedirectStandardOutput = true;
                Cmd.UseShellExecute = false;

                Console.WriteLine("Going to run:" + Cmd.FileName + " " + Cmd.Arguments);
                // Run Process
                Process p = Process.Start(Cmd);
                System.IO.StreamReader stdOutput = p.StandardOutput;

                // Loop until process is finised
                while (!p.HasExited)
                {
                    Thread.Sleep(1000);
                }

                // Display Output from process
                string Output = stdOutput.ReadToEnd();
                T.Status = Output.Split('\n')[0];
                T.Response = Output;

                if (T.LogDb == 1)
                {
                    LogTask(T);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Source + " " + e.Message);
                Console.WriteLine(e.StackTrace);
            }

        }

        static void LogTask(Object stateInfo)
        {

            SqlConnection conn = new SqlConnection();
            string sqltext = "";
            try
            {
                Task T = (Task)stateInfo;
                conn = new SqlConnection(ConnectionString);
                conn.Open();

                sqltext = @"insert into 
                                logstore (task_id, status, response) 
                                values (#task_id#,'#status#','#response#')";

                sqltext = sqltext.Replace("#response#", T.Response);
                sqltext = sqltext.Replace("#task_id#", T.TaskId);
                sqltext = sqltext.Replace("#status#", T.Status);

                SqlCommand cmd = new SqlCommand(sqltext, conn);
                SqlDataReader rdr = null;
                rdr = cmd.ExecuteReader();


            }
            catch (Exception e)
            {
                Console.WriteLine("{0} {1} {2}", e.Source, e.Message, e.StackTrace);
            }
            finally
            {
                conn.Close();
            }
        }

        static void DoTasks()
        {
            try
            {
                //Run All Tasks
                foreach (Task T in AllTasks)
                    ThreadPool.QueueUserWorkItem(new WaitCallback(LaunchTask), T);
                

                int Available, Max, y;

                // Wait until all threads complete excution
                do
                {

                    Thread.Sleep(5000);

                    ThreadPool.GetAvailableThreads(out Available, out y);
                    ThreadPool.GetMaxThreads(out Max, out y);

                }
                while (Available != Max);
            }
            catch (Exception e)
            {
                Console.WriteLine("{0} {1} {2}", e.Source, e.Message, e.StackTrace);
            }
        }

        
    }
}
